﻿using System.IO;
using System.Text;
using System;

namespace ProtocolTool
{
    partial class Program
    {
        //ClassTypeScript
        public static readonly string Filepath_ClassTypeScript = @"proto.ts";

        public static readonly string Template_ClassTypeScript = @"
export namespace vpb {

    //协议基类
    export class ProtocolMsgBase {
        // 协议号
        public _protocol:number = 0;
        // 结果码
        public _result:number = 0;
        // Pin码
        public Pin:number = 0;
        // 玩家唯一ID
        public Puid:number = 0;
        // 附加中转信息
        public Shuttle:string = '';

        // 构造函数
        public constructor(protocol:number) {
            this._protocol = protocol
        }
    }

$Class$

$Pids$

$Enums$

}
";

        public static bool TypeScriptIsNumbaer(string v)
        {
            if (v == "byte"
                || v == "short"
                || v == "int"
                || v == "uint"
                || v == "long"
                || v == "float"
                || v == "double"
                || v == "DateTime"
                || v == "TimeSpan"
                || v == "dt"
                || v == "ts"
                )
            {
                return true;
            }
            return false;
        }
        public static string TypeScriptCheckNumbaer(string v)
        {
            if (TypeScriptIsNumbaer(v))
            {
                return "number";
            }
            return v;
        }

        //成员和初始化
        public static string GetClassBodyTypeScriptFromNode(CClassNode v)
        {
            var sb = new StringBuilder();

            if (v.Desc != "")
            {
                sb.Append($"\t\t// {v.Desc}\r\n");
            }
            switch (v.Ctype)
            {
                case "bool":
                    sb.Append($"\t\tpublic {v.Body}: boolean = false;");
                    break;

                case "string":
                    sb.Append($"\t\tpublic {v.Body}: string = '';");
                    break;

                case "list":
                    //sb.Append($"    var {v.Body}:{v.Ctype1}[];");
                    sb.Append($"\t\tpublic {v.Body}: {TypeScriptCheckNumbaer(v.Ctype1)}[] = [];");
                    break;

                case "dict":
                    //sb.Append($"    var {v.Body}:{v.Ctype1}[];");
                    //sb.Append($"\t\tpublic {v.Body}: any;");
                    //sb.Append($"\t\tpublic {v.Body} = new Map<{v.Ctype1}, {v.Ctype2}>();");
                    sb.Append($"\t\tpublic {v.Body} = new Map();");
                    break;

                default:
                    if (TypeScriptIsNumbaer(v.Ctype))
                    {
                        sb.Append($"\t\tpublic {v.Body}: number = 0;");
                    }
                    else if(DictEnum.ContainsKey(v.Ctype))
                    {
                        sb.Append($"\t\tpublic {v.Body}: number = 0;");
                    }
                    else
                    {
                        sb.Append($"\t\tpublic {v.Body}: {v.Ctype} = new {v.Ctype}();");
                    }
                    break;
            }
            return sb.ToString();
        }

        /// <summary>
        /// 生成结构体文件 TypeScript
        /// </summary>
        private static void ProtocolConverterClassTypeScript()
        {
            Show("ProtocolConverterClassTypeScript");
            var sb = new StringBuilder();
            var sbPids = new StringBuilder();
            var sbEnums = new StringBuilder();

            sbPids.AppendLine($"\texport enum EPid{{");
            foreach (var kvp in DictClass)
            {
                if (kvp.Value.Desc != "")
                {
                    sb.Append($"\t// {kvp.Value.Desc} \r\n");
                }
                if (kvp.Value.ClassType == 0)
                {
                    sb.AppendLine($"\texport class {kvp.Value.Name} extends ProtocolMsgBase {{");
                    sb.AppendLine($"\t\tpublic constructor() {{ super({kvp.Value.Id}); }}");
                    sbPids.AppendLine($"\t\t{kvp.Value.NameId} = {kvp.Value.Id},");
                }
                else
                {
                    sb.AppendLine($"\texport class {kvp.Value.Name} {{");
                }
                //结构体
                foreach (var kvp2 in kvp.Value.DictBody)
                {
                    sb.AppendLine($"{GetClassBodyTypeScriptFromNode(kvp2.Value)}");
                }
                sb.AppendLine("\t};");
            }
            sbPids.AppendLine($"\t}}");

            foreach (var kvp in DictEnum)
            {
                if (kvp.Value.Desc != "")
                {
                    sbEnums.AppendLine($"\t// {kvp.Value.Desc}");
                }
                sbEnums.AppendLine($"\texport enum {kvp.Value.Name} {{");
                foreach (var kvp2 in kvp.Value.DictBody)
                {
                    if (kvp2.Value.Desc != "")
                    {
                        sbEnums.AppendLine($"\t\t// {kvp2.Value.Desc}");
                    }
                    if (kvp2.Value.Value != -100000)
                    {
                        sbEnums.AppendLine($"\t\t{kvp2.Value.Body} = {kvp2.Value.Value},");
                    }
                    else
                    {
                        sbEnums.AppendLine($"\t\t{kvp2.Value.Body},");
                    }
                }
                sbEnums.AppendLine($"\t}}");
            }

            string txt = Template_ClassTypeScript;
            FileStream fs = new FileStream(PathCurrent + Filepath_ClassTypeScript, FileMode.Create);
            StreamWriter sw = new StreamWriter(fs, Encoding.UTF8);
            txt = txt.Replace("$Class$", sb.ToString());
            txt = txt.Replace("$Pids$", sbPids.ToString());
            txt = txt.Replace("$Enums$", sbEnums.ToString());
            sw.Write(txt);
            sw.Close();
            Show("输出文件：" + Filepath_ClassTypeScript);
        }

    }
}